const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

console.log('🚀 开始构建ruoyi-node-midway独立部署包...');

// 文件过滤函数 - 排除TypeScript文件和开发文件
function shouldIncludeFile(filePath) {
  const fileName = path.basename(filePath);
  const ext = path.extname(filePath);
  
  // 排除的文件类型
  const excludeExtensions = ['.ts', '.tsx', '.d.ts'];
  const excludeFiles = ['tsconfig.json', 'jest.config.js', '.gitignore', '.eslintrc.js'];
  const excludeDirs = ['test', 'tests', '__tests__', 'coverage', '.git', '.vscode'];
  
  // 检查文件扩展名
  if (excludeExtensions.includes(ext)) {
    return false;
  }
  
  // 检查文件名
  if (excludeFiles.includes(fileName)) {
    return false;
  }
  
  // 检查目录名
  const dirName = path.dirname(filePath);
  const dirs = dirName.split(path.sep);
  for (const dir of dirs) {
    if (excludeDirs.includes(dir)) {
      return false;
    }
  }
  
  return true;
}

// 递归复制目录，排除TypeScript文件
function copyDirExcludeTs(src, dest) {
  if (!fs.existsSync(src)) return;
  
  if (!fs.existsSync(dest)) {
    fs.mkdirSync(dest, { recursive: true });
  }
  
  const entries = fs.readdirSync(src, { withFileTypes: true });
  for (const entry of entries) {
    const srcPath = path.join(src, entry.name);
    const destPath = path.join(dest, entry.name);
    
    if (entry.isDirectory()) {
      // 递归处理子目录
      copyDirExcludeTs(srcPath, destPath);
    } else {
      // 只复制允许的文件
      if (shouldIncludeFile(srcPath)) {
        fs.copyFileSync(srcPath, destPath);
      }
    }
  }
}

// 1. 设置构建目录
const buildDir = 'dist-package';
const timestamp = new Date().toISOString().split('T')[0];
const packageName = `ruoyi-node-midway-production-${timestamp}.tar.gz`;

console.log('🧹 设置构建目录...');
if (fs.existsSync(buildDir)) {
  fs.rmSync(buildDir, { recursive: true, force: true });
}
fs.mkdirSync(buildDir, { recursive: true });

// 2. 复制必要文件
console.log('📋 复制必要文件...');
const filesToCopy = [
  'bootstrap.js',
  'package.json',
  'dist',
  'public'
];

// 单独处理SQL文件，只复制SQL文件而不复制整个src目录
console.log('📋 复制SQL文件...');
const sqlSrcDir = path.join(process.cwd(), 'src/sql');
const sqlDestDir = path.join(buildDir, 'sql');
if (fs.existsSync(sqlSrcDir)) {
  fs.mkdirSync(sqlDestDir, { recursive: true });
  // 只复制.sql文件，排除.ts文件
  const files = fs.readdirSync(sqlSrcDir);
  files.forEach(file => {
    if (file.endsWith('.sql')) {
      fs.copyFileSync(
        path.join(sqlSrcDir, file),
        path.join(sqlDestDir, file)
      );
    }
  });
  console.log('  ✅ 复制SQL文件');
} else {
  console.log('  ⚠️  跳过SQL文件 (目录不存在)');
}

filesToCopy.forEach(file => {
  const srcPath = path.join(process.cwd(), file);
  const destPath = path.join(buildDir, file);
  
  if (fs.existsSync(srcPath)) {
    if (fs.statSync(srcPath).isDirectory()) {
      // 使用过滤函数复制目录，排除TypeScript文件
      copyDirExcludeTs(srcPath, destPath);
    } else {
      // 确保目标文件的父目录存在
      const destParent = path.dirname(destPath);
      if (!fs.existsSync(destParent)) {
        fs.mkdirSync(destParent, { recursive: true });
      }
      // 只复制允许的文件
      if (shouldIncludeFile(srcPath)) {
        fs.copyFileSync(srcPath, destPath);
      }
    }
    console.log(`  ✅ 复制 ${file}`);
  } else {
    console.log(`  ⚠️  跳过 ${file} (文件不存在)`);
  }
});

// 3. 创建生产环境配置
console.log('📝 创建生产环境配置...');
const prodConfigPath = path.join(buildDir, 'dist/config/config.prod.js');
if (fs.existsSync(prodConfigPath)) {
  let config = fs.readFileSync(prodConfigPath, 'utf8');
  // 确保生产环境配置正确
  config = config.replace(/NODE_ENV.*?local/g, 'NODE_ENV: \'production\'');
  fs.writeFileSync(prodConfigPath, config);
  console.log('  ✅ 生产环境配置已更新');
}

// 4. 创建启动脚本
console.log('📝 创建启动脚本...');
const startScript = `#!/bin/bash
# Ruoyi Node.js Midway 启动脚本

echo "🚀 启动 Ruoyi Node.js Midway 应用..."

# 检查Node.js环境
if ! command -v node &> /dev/null; then
    echo "❌ 错误: 未找到Node.js，请先安装Node.js"
    exit 1
fi

# 检查依赖
if [ ! -d "node_modules" ]; then
    echo "📦 安装生产依赖..."
    npm install --production
fi

# 设置环境变量
export NODE_ENV=production
export PORT=7002

# 启动应用
echo "🎯 启动应用在端口 7002..."
node bootstrap.js
`;

fs.writeFileSync(path.join(buildDir, 'start.sh'), startScript);
fs.chmodSync(path.join(buildDir, 'start.sh'), '755');
console.log('  ✅ 启动脚本已创建');

// 5. 创建PM2配置文件
console.log('📝 创建PM2配置文件...');
const pm2Config = `module.exports = {
  apps: [{
    name: 'ruoyi-node-midway',
    script: 'bootstrap.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production',
      PORT: 7002
    },
    log_file: './logs/combined.log',
    out_file: './logs/out.log',
    error_file: './logs/error.log',
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    max_memory_restart: '1G',
    node_args: '--max-old-space-size=1024'
  }]
}`;

fs.writeFileSync(path.join(buildDir, 'ecosystem.config.js'), pm2Config);
console.log('  ✅ PM2配置文件已创建');

// 6. 创建日志目录
console.log('📁 创建日志目录...');
fs.mkdirSync(path.join(buildDir, 'logs'), { recursive: true });
console.log('  ✅ 日志目录已创建');

// 7. 安装生产依赖
console.log('📦 安装生产依赖...');
try {
  execSync('npm install --production', { 
    cwd: buildDir, 
    stdio: 'inherit' 
  });
  console.log('  ✅ 生产依赖安装完成');
} catch (error) {
  console.log('  ⚠️  生产依赖安装失败，请手动执行: npm install --production');
}

// 8. 创建部署包
console.log('📦 创建部署包...');
try {
  execSync(`tar -czf ${packageName} -C ${buildDir} .`);
  console.log(`✅ 部署包创建完成: ${packageName}`);
  
  // 显示文件信息
  const stats = fs.statSync(packageName);
  const fileSizeInMB = (stats.size / (1024 * 1024)).toFixed(2);
  console.log(`📊 文件大小: ${fileSizeInMB} MB`);
  
} catch (error) {
  console.error('❌ 创建部署包失败:', error.message);
  process.exit(1);
}

console.log('🎉 打包完成！');
console.log(`📦 部署包: ${packageName}`);
console.log(`📁 构建目录: ${buildDir}/`);
console.log('');
console.log('🚀 部署说明:');
console.log('1. 将部署包上传到服务器');
console.log('2. 解压: tar -xzf ' + packageName);
console.log('3. 进入目录: cd ruoyi-node-midway');
console.log('4. 启动应用: ./start.sh 或 pm2 start ecosystem.config.js');